home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / pine3.96.tar.gz / pine3.96.tar / pine3.96 / imap / ANSI / c-client / misc.c < prev    next >
C/C++ Source or Header  |  1995-04-19  |  8KB  |  252 lines

  1. /*
  2.  * Program:    Miscellaneous utility routines
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date:    5 July 1988
  13.  * Last Edited:    19 April 1995
  14.  *
  15.  * Sponsorship:    The original version of this work was developed in the
  16.  *        Symbolic Systems Resources Group of the Knowledge Systems
  17.  *        Laboratory at Stanford University in 1987-88, and was funded
  18.  *        by the Biomedical Research Technology Program of the National
  19.  *        Institutes of Health under grant number RR-00785.
  20.  *
  21.  * Original version Copyright 1988 by The Leland Stanford Junior University
  22.  * Copyright 1995 by the University of Washington
  23.  *
  24.  *  Permission to use, copy, modify, and distribute this software and its
  25.  * documentation for any purpose and without fee is hereby granted, provided
  26.  * that the above copyright notices appear in all copies and that both the
  27.  * above copyright notices and this permission notice appear in supporting
  28.  * documentation, and that the name of the University of Washington or The
  29.  * Leland Stanford Junior University not be used in advertising or publicity
  30.  * pertaining to distribution of the software without specific, written prior
  31.  * permission.  This software is made available "as is", and
  32.  * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
  33.  * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
  34.  * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  35.  * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
  36.  * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
  37.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  38.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  39.  * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
  40.  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  41.  *
  42.  */
  43.  
  44.  
  45. #include <ctype.h>
  46. #include "mail.h"
  47. #include "osdep.h"
  48. #include "misc.h"
  49.  
  50. /* Convert string to all uppercase
  51.  * Accepts: string pointer
  52.  * Returns: string pointer
  53.  */
  54.  
  55. char *ucase (char *s)
  56. {
  57.   char c;
  58.   char *ret = s;
  59.                 /* if lowercase covert to upper */
  60.   for (; c = *s; s++) if (islower (c)) *s -= 'a'-'A';
  61.   return (ret);            /* return string */
  62. }
  63.  
  64.  
  65. /* Convert string to all lowercase
  66.  * Accepts: string pointer
  67.  * Returns: string pointer
  68.  */
  69.  
  70. char *lcase (char *s)
  71. {
  72.   char c;
  73.   char *ret = s;
  74.                 /* if uppercase covert to lower */
  75.   for (; c = *s; s++) if (isupper (c)) *s += 'a'-'A';
  76.   return (ret);            /* return string */
  77. }
  78.  
  79.  
  80. /* Copy string to free storage
  81.  * Accepts: source string
  82.  * Returns: free storage copy of string
  83.  */
  84.  
  85. char *cpystr (char *string)
  86. {
  87.   if (string) {            /* make sure argument specified */
  88.     char *dst = (char *) fs_get (1+strlen (string));
  89.     strcpy (dst,string);
  90.     return (dst);
  91.   }
  92.   else return NIL;
  93. }
  94.  
  95. /* Returns index of rightmost bit in word
  96.  * Accepts: pointer to a 32 bit value
  97.  * Returns: -1 if word is 0, else index of rightmost bit
  98.  *
  99.  * Bit is cleared in the word
  100.  */
  101.  
  102. unsigned long find_rightmost_bit (unsigned long *valptr)
  103. {
  104.   register long value= *valptr;
  105.   register long clearbit;    /* bit to clear */
  106.   register bitno;        /* bit number to return */
  107.   if (value == 0) return (-1);    /* no bits are set */
  108.   if (value & 0xFFFF) {        /* low order halfword has a bit? */
  109.     bitno = 0;            /* yes, start with bit 0 */
  110.     clearbit = 1;        /* which has value 1 */
  111.   } else {            /* high order halfword has the bit */
  112.     bitno = 16;            /* start with bit 16 */
  113.     clearbit = 0x10000;        /* which has value 10000h */
  114.     value >>= 16;        /* and slide the halfword down */
  115.   }
  116.   if (!(value & 0xFF)) {    /* low quarterword has a bit? */
  117.     bitno += 8;            /* no, start 8 bits higher */
  118.     clearbit <<= 8;        /* bit to clear is 2^8 higher */
  119.     value >>= 8;        /* and slide the quarterword down */
  120.   }
  121.   while (T) {            /* search for bit in quarterword */
  122.     if (value & 1) break;    /* found it? */
  123.     value >>= 1;        /* now, slide the bit down */
  124.     bitno += 1;            /* count one more bit */
  125.     clearbit <<= 1;        /* bit to clear is 1 bit higher */
  126.   }
  127.   *valptr ^= clearbit;        /* clear the bit in the argument */
  128.   return (bitno);        /* and return the bit number */
  129. }
  130.  
  131. /* Return minimum of two integers
  132.  * Accepts: integer 1
  133.  *        integer 2
  134.  * Returns: minimum
  135.  */
  136.  
  137. long min (long i,long j)
  138. {
  139.   return ((i < j) ? i : j);
  140. }
  141.  
  142.  
  143. /* Return maximum of two integers
  144.  * Accepts: integer 1
  145.  *        integer 2
  146.  * Returns: maximum
  147.  */
  148.  
  149. long max (long i,long j)
  150. {
  151.   return ((i > j) ? i : j);
  152. }
  153.  
  154. /* Case independent search (fast on 32-bit machines)
  155.  * Accepts: base string
  156.  *        length of base string
  157.  *        pattern string
  158.  *        length of pattern string
  159.  * Returns: T if pattern exists inside base, else NIL
  160.  */
  161.  
  162. #define Word unsigned long
  163.  
  164. long search (char *s,long c,char *pat,long patc)
  165. {
  166.   register Word m;
  167.   long cc;
  168.   union {
  169.     unsigned long wd;
  170.     char ch[9];
  171.   } wdtest;
  172.   strcpy (wdtest.ch,"AAAA1234");/* constant for word testing */
  173.                 /* validate arguments, c becomes # of tries */
  174.   if (!(s && c > 0 && pat && patc > 0 && (c -= (patc - 1)) > 0)) return NIL;
  175.                 /* do slow search if long is not 4 chars */
  176.   if (wdtest.wd != 0x41414141) return ssrc (&s,&c,pat,(long) T);
  177.   /*
  178.    * Fast search algorithm XORs the mask with each word from the base string
  179.    * and complements the result. This will give bytes of all ones where there
  180.    * are matches.  We then mask out the high order and case bits in each byte
  181.    * and add 21 (case + overflow) to all the bytes.  If we have a resulting
  182.    * carry, then we have a match.
  183.    */
  184.   if (cc = ((int) s & 3)) {    /* any chars before word boundary? */
  185.     c -= (cc = 4 - cc);        /* yes, calculate how many, account for them */
  186.                 /* search through those */
  187.     if (ssrc (&s,&cc,pat,(long) NIL)) return T;
  188.   }
  189.   m = *pat * 0x01010101;    /* search mask */
  190.   do {                /* interesting word? */
  191.     if (0x80808080&(0x21212121+(0x5F5F5F5F&~(m^*(Word *) s)))) {
  192.                 /* yes, commence a slow search through it */
  193.       if (ssrc (&s,&c,pat,(long) NIL)) return T;
  194.     }
  195.     else s += 4,c -= 4;        /* try next word */
  196.   } while (c > 0);        /* continue until end of string */
  197.   return NIL;            /* string not found */
  198. }
  199.  
  200. /* Case independent slow search within a word
  201.  * Accepts: base string
  202.  *        number of tries left
  203.  *        pattern string
  204.  *        multi-word hunt flag
  205.  * Returns: T if pattern exists inside base, else NIL
  206.  */
  207.  
  208. long ssrc (char **base,long *tries,char *pat,long multiword)
  209. {
  210.   register char *s = *base;
  211.   register long c = multiword ? *tries : min (*tries,(long) 4);
  212.   register char *p = pat;
  213.                 /* search character at a time */
  214.   if (c > 0) do if (!((*p ^ *s++) & (char) 0xDF)) {
  215.     char *ss = s;        /* remember were we began */
  216.     do if (!*++p) return T;    /* match case-independent until end */
  217.     while (!((*p ^ *s++) & (char) 0xDF));
  218.     s = ss;            /* try next character */
  219.     p = pat;            /* start at beginning of pattern */
  220.   } while (--c);        /* continue if multiword or not at boundary */
  221.   *tries -= s - *base;        /* update try count */
  222.   *base = s;            /* update base */
  223.   return NIL;            /* string not found */
  224. }
  225.  
  226. /* Wildcard pattern match
  227.  * Accepts: base string
  228.  *        pattern string
  229.  * Returns: T if pattern matches base, else NIL
  230.  */
  231.  
  232. long pmatch (char *s,char *pat)
  233. {
  234.   switch (*pat) {
  235.   case '*':            /* match 0 or more characters */
  236.     if (!pat[1]) return T;    /* pattern ends with * wildcard */
  237.                 /* if still more, hunt through rest of base */
  238.     do if (pmatch (s,pat+1)) return T;
  239.     while (*s++);
  240.     break;
  241.   case '%':            /* match 1 character (RFC-1176) */
  242.   case '?':            /* match 1 character (common) */
  243.     return pmatch (s+1,pat+1);    /* continue matching remainder */
  244.   case '\0':            /* end of pattern */
  245.     return *s ? NIL : T;    /* success if also end of base */
  246.   default:            /* match this character */
  247.     return ((isupper (*pat) ? *pat + 'a'-'A' : *pat) ==
  248.         (isupper (*s) ? *s + 'a'-'A' : *s)) ? pmatch (s+1,pat+1) : NIL;
  249.   }
  250.   return NIL;
  251. }
  252.